﻿//
// I AM THE SERVER SIDE SIMULATION
// I AM THE GAME LOGIC! I AM THE GOATS AND I AM THE WORLD!
//

using System.Collections.Generic;
using System.Linq;
using BoatNGoat.Logic.Map.Generator;
using BoatNGoat.Server;
using BoatNGoat.Logic.Map;
using SharpDX;
using Water = BoatNGoat.SharedLogic.Water;

namespace BoatNGoat.Logic
{
    public class Simulation : IUpdateable
    {
        public List<IMobile> GetGoats()
        {
            return _goats;
        }

        private readonly List<IMobile> _goats = new List<IMobile>();
        private Water.Ocean _ocean = new Water.Ocean();
        private IMap _map;
        private readonly MobFactory _factory = new MobFactory();

        public void Init()
        {
            List<IHeightFunction> mapGenerators = new List<IHeightFunction>();
            mapGenerators.Add(new DiamondSquareFractalTerrain(500, 500));
            mapGenerators.Add(new RegularBumpsGenerator());

            var addedGenerators = new CompositionFunction(mapGenerators, list => (list.Sum() / list.Count ) );

            _map = Map.Map.CreateMapFromHeightFunction(addedGenerators, 300,400);

            SpawnPlacer placer = new SpawnPlacer
                {
                    HerdTerritorySize = new TerritorySize {Width = 15, Height = 15},
                    MaxHerdSize = 50,
                    MinimumLandAroundSpawnPoint = 1.5
                };

            var goatSpawns = placer.CreateSpawnPoints(_map);

            foreach (var spawn in goatSpawns)
            {
                _goats.Add(_factory.MakeGoat(spawn, _map));
            }
            var reader = new Water.FauxOceanReader();
            reader.ReadInto(ref _ocean);
        }

        public PlayerMob InitPlayer()
        {
            SpawnPlacer placer = new SpawnPlacer();
            placer.MinimumLandAroundSpawnPoint = 4;
            SpawnPoint spawn = placer.CreateSingleSpawn(_map);

            PlayerMob man = _factory.MakePlayer(spawn, _map);

            _goats.Add(man);

            return man;
        }

        public void Update(ServerTime serverTime)
        {
            foreach (Goat t in _goats)
            {
                t.Update(serverTime);
            }
            _ocean.Update(serverTime.ElapsedGameTime);
        }

        public IMap GetMap()
        {
            return _map;
        }
    }
}
